/*
 * Main.java
 *
 * Created on 2007. mC!rcius 12., 15:33
 *
 */

package laborhazi;
import java.io.*;
/*import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;*/

/**
 * The game class is responsible for the game creation and maintaining the 
 * connection between the model elements and other types 
 * ie. controllers <-> view
 *
 * @author nyuszik
 */
public class Game {
	
    /**
	 * Mandatory serial version UID
	 */
	private static final long serialVersionUID = 1L;
	
	public HighScore score = null;
    public Toolbar toolbar = null;
    public Field stage = null;
    public String name = null;
    public Viewer view = null;
    public Controller controll = null;
    private MyThread model = null;
    private Test test = null; //testing only
    public boolean END = false;
    /* parse */
    private int lemingNum = 0, startNum = 0, finishNum = 0;
    private boolean parseOK = false;
    String filename = null;
	int posAct = -1;
    /** 
     * constructor of the Game
     */
    public Game(Test t, String name) {
        test = t;
        ;
        model = new MyThread("game", this);
        if (name != null) {
        	filename = new String (name);
        } else filename = "none";
        System.out.println("Test number: " + test.testNum + "\n" + "A new game is created");
        controll = new Controller(this);
        initialize();
        view = new Viewer(this, stage);
        model.start();
    }
    public Game(String name) {
        model = new MyThread("game", this);
        if (name != null) {
        	filename = new String (name);
        } else filename = "none";
        //System.out.println("Test number: " + test.testNum + "\n" + "A new game is created");
        controll = new Controller(this);
        initialize();
        view = new Viewer(this, stage);
        model.start();
    }
    
    /**
     * @param args the command line arguments
     */
    /*
    public static void main(String[] args) {
        // TODO code application logic here
    }*/
    /** 
     * initialize the game, getting name, creating objects essential 
     * for gameplay
     */
    public void initialize() {
    	System.out.println("initialize");  
    	
        try { this.parse();
    	} catch (Exception e){
    		System.exit(-1);
    	}
        score = new HighScore(this);
    	}
      
    /** 
     * parse the map from file, and create object storing it
     */
    private void parse() throws NumberFormatException, NullPointerException{
    	BufferedReader in; 
    	String line = null;
    	String sub = null;
    	/*java.io.File f = new java.io.File(".");
    	try {
			System.out.println(f.getCanonicalPath());
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}*/
    	int dimX=-1, dimY=-1, dir=-1; // parameters of the inputs
    	int pos[];
    	int parameters = -1; //number of desired parameters
    	int size = -1, i; 
    	//int posFirst,posSecond; // position of the separator
    	//int posAct = -1;
        //boolean parseOK = false;
    	pos = new int[2];
    	
    	/* open file if available */
    	try {
			in = new BufferedReader(new FileReader(filename));
		} catch (FileNotFoundException e) {
			/* open standard input if no file exists */
			in = new BufferedReader(new InputStreamReader(System.in));
			//e.printStackTrace();
		}
		try {
			while ( (line = in.readLine()) != null ) {
				/* init positions and parse error value */
				parseOK = false;
				//posFirst = 0;
				//posSecond = 0;
				posAct = 0;
				if ( line.startsWith("field ") ) {
					parameters = 2;
					for (i = 1; i <= parameters; ++i) {
						/* mark parameter */
						try {	sub = mark(line,i, parameters); 
						}	catch (NumberFormatException e){
				    		throw new NumberFormatException();
				    	}
						/* parse parameters to integer */
						switch (i) {
						case 1: {
							dimX = Integer.parseInt(sub);
							break;
							}
						case 2: {
							dimY = Integer.parseInt(sub);
							break;
							}
						}
					}
					if (parseOK == false) {
						break;
					}
					stage = new Field(dimX, view);
					/* Create Viewer Area Map to help exchange bitween Viewer and field*/
					size = dimX;
				}
				//lemming
				else if ( line.startsWith("lemming ") ) {
					if (size == -1) {
						//System.out.println("Parse Error");
						throw new NumberFormatException();
					}
					parameters = 3;
					for (i = 1; i <= parameters; ++i) {
						/* mark parameter */
						try {	sub = mark(line,i, parameters); 
						} catch (NumberFormatException e){
							throw new NumberFormatException();
							}							
						/* parse parameters to integer */
						switch (i) {
						case 1: {
							dimX = Integer.parseInt(sub);
							if ( dimX > size || dimX <= 0 ) throw new NumberFormatException();
							break;
							}
						case 2: {
							dimY = Integer.parseInt(sub);
							if ( dimY > size || dimY <= 0 ) throw new NumberFormatException();
							break;
							}
						case 3: {
							dir = Integer.parseInt(sub);
							if ( dir != 1 && dir != 0) throw new NumberFormatException();
							break;
							}
						}
					}					
					if (parseOK == false) {
						break;
					} else {
						stage.incLemming();
						pos[0] = dimX;
						pos[1] = dimY;
						if (null == stage.check(pos)) {
							stage.put(new Lemming(stage.getLemmingNum(), stage, dir), pos);
						} else {
							throw new NumberFormatException();
						}
					}
				}
				// stone
				else if ( line.startsWith("stone ") ) {
					if (size == -1) {
						//System.out.println("Parse Error");
						throw new NumberFormatException();
					}
					parameters = 2;
					for (i = 1; i <= parameters; ++i) {
						/* mark parameter */
						try {	sub = mark(line,i, parameters); 
						}	catch (NumberFormatException e){
				    		throw new NumberFormatException();
				    	}
						/* parse parameters to integer */
						switch (i) {
						case 1: {
							dimX = Integer.parseInt(sub);
							if ( dimX > size || dimX <= 0 ) throw new NumberFormatException();
							break;
							}
						case 2: {
							dimY = Integer.parseInt(sub);
							if ( dimY > size || dimY <= 0 ) throw new NumberFormatException();
							break;
							}
						}
					}
					//TODO create stone
					if (parseOK == false) {
						break;
					} else {
						pos[0] = dimX;
						pos[1] = dimY;
						if (null == stage.check(pos)) {
							stage.put(new Stone(stage), pos);
						} else {
							//System.out.println("NERAKDRA!!!!");
							throw new NumberFormatException();
						}
					}
				}
				//finishfield
				else if ( line.startsWith("finishfield ") ) {
					if (size == -1 || finishNum > 0) {
						//System.out.println("Parse Error");
						throw new NumberFormatException();
					}
					parameters = 2;
					for (i = 1; i <= parameters; ++i) {
						/* mark parameter */
						try {	sub = mark(line,i, parameters); 
						}	catch (NumberFormatException e){
				    		throw new NumberFormatException();
				    	}
						/* parse parameters to integer */
						switch (i) {
						case 1: {
							dimX = Integer.parseInt(sub);
							if ( dimX > size || dimX <= 0 ) throw new NumberFormatException();
							break;
							}
						case 2: {
							dimY = Integer.parseInt(sub);
							if ( dimY > size || dimY <= 0 ) throw new NumberFormatException();
							break;
							}
						}
					}
					//TODO create finishfield
					if (parseOK == false) {
						break;
					} else {
						pos[0] = dimX;
						pos[1] = dimY;
						++finishNum;
						if (null == stage.check(pos)) {
							stage.put(new FinishField(stage), pos);
						} else {
							System.out.println("NERAKDRA!!!!");
							throw new NumberFormatException();
						}
					}
				}
				//startfield
				else if ( line.startsWith("startfield ") ) {
					if (size == -1 || startNum > 0) {
						//System.out.println("Parse Error");
						throw new NumberFormatException();
					}
					parameters = 2;
					for (i = 1; i <= parameters; ++i) {
						/* mark parameter */
						try {	sub = mark(line,i, parameters); 
						}	catch (NumberFormatException e){
				    		throw new NumberFormatException();
				    	}
						/* parse parameters to integer */
						switch (i) {
						case 1: {
							dimX = Integer.parseInt(sub);
							if ( dimX > size || dimX <= 0 ) throw new NumberFormatException();
							break;
							}
						case 2: {
							dimY = Integer.parseInt(sub);
							if ( dimY > size || dimY <= 0 ) throw new NumberFormatException();
							break;
							}
						}
					}
					//TODO create startfield
					if (parseOK == false) {
						break;
					} else {
						pos[0] = dimX;
						pos[1] = dimY;
						++startNum;
						if (null == stage.check(pos)) {
							stage.put(new StartField(15, stage), pos);
						} else {
							//System.out.println("NERAKDRA!!!!");
							throw new NumberFormatException();
						}
					}
					
				}
				//tool
				else if ( line.startsWith("tool ") ) {
					if (size == -1) {
						//System.out.println("Parse Error");
						throw new NumberFormatException();
					}
					parameters = 1;
					for (i = 1; i <= parameters; ++i) {
						/* mark parameter */
						try {	sub = mark(line,i, parameters); 
						}	catch (NumberFormatException e){
				    		throw new NumberFormatException();
				    	}
						/* parse parameters to integer */
						switch (i) {
						case 1: {
							dimX = Integer.parseInt(sub);
							if ( dimX > 5 || dimX <= 0 ) throw new NumberFormatException();
							break;
							}
						}
					}
					//TODO create tool
					if (toolbar == null) {
						toolbar = new Toolbar(stage);
						}
					switch (dimX) {
					case 1: {
						toolbar.add(new Barricade(stage));
						break;
						}
					case 2: {
						toolbar.add(new Parachute(stage));
						break;
						}
					case 3: {
						toolbar.add(new Erector(stage));
						break;
						}
					case 4: {
						toolbar.add(new Drill(stage));
						break;
						}
					case 5: {
						toolbar.add(new Explosive(stage));
						break;
						}
					}
					
					if (parseOK == false) {
						break;
						}
				}
				//highlight
				else if ( line.startsWith("highlight ") ) {
					if (size == -1) {
						//System.out.println("Parse Error");
						throw new NumberFormatException();
					}
					parameters = 1;
					for (i = 1; i <= parameters; ++i) {
						/* mark parameter */
						try {	sub = mark(line,i, parameters); 
						}	catch (NumberFormatException e){
				    		throw new NumberFormatException();
				    	}
						/* parse parameters to integer */
						switch (i) {
						case 1: {
							dimX = Integer.parseInt(sub);
							if ( dimX > 5 || dimX <= 0 ) throw new NumberFormatException();
							break;
							}
						}
					}
					switch (dimX) {
					case 1: {
						toolbar.highlight(new Barricade());
						break;
						}
					case 2: {
						toolbar.highlight(new Parachute());
						break;
						}
					case 3: {
						toolbar.highlight(new Erector());
						break;
						}
					case 4: {
						toolbar.highlight(new Drill());
						break;
						}
					case 5: {
						toolbar.highlight(new Explosive());
						break;
						}
					}
					
					if (parseOK == false) {
						break;
						}
				}
				//listLemmings
				else if ( line.startsWith("list") ) {
					BufferedReader console;
					String choose;
					int num = -1;
					stage.listLemming();
					
			        console = new BufferedReader(new InputStreamReader(System.in));
			        choose = console.readLine();
			        if ((num = Integer.parseInt(choose)) != -1) {
			        	stage.getLemming(num);
			        }
				}
				//give
				else if ( line.startsWith("give ") ) {
					if (size == -1) {
						//System.out.println("Parse Error");
						throw new NumberFormatException();
					}
					parameters = 1;
					for (i = 1; i <= parameters; ++i) {
						/* mark parameter */
						try {	sub = mark(line,i, parameters); 
						}	catch (NumberFormatException e){
				    		throw new NumberFormatException();
				    	}
						/* parse parameters to integer */
						switch (i) {
						case 1: {
							dimX = -1;
							dimX = Integer.parseInt(sub);
							if ( dimX <= 0 ) throw new NumberFormatException();
							break;
							}
						}
					}
					if (dimX != -1) {
			        	toolbar.give(stage.getLemming(dimX));
			        } else throw new NumberFormatException();
					
					if (parseOK == false) {
						break;
						}
				}
				//end
				else if ( line.startsWith("end") ){
					break;
				}
				else {
					//System.out.println("Parse Error");
					throw new NumberFormatException();
				}
			} //end of while
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    /** 
     * setting the mark in the line of data when parsing
     */
    private String mark(String line, int i, int parameters) throws NumberFormatException{
    	
    	String sub = null;
    	int posFirst = 0, posSecond = 0;
   	
    	if ( (posFirst = line.indexOf(' ', posAct)) == -1) { // Position of FIRST space
			//System.out.println("Parse Error");
			throw new NumberFormatException();
		}
		if ( (posSecond = line.indexOf(' ', posFirst + 1 )) == -1 ) { // Position of SECOND space
			if (i == parameters){
				this.parseOK = true;
				sub = line.substring(posFirst + 1, line.length()); // last word
			} else {
				//System.out.println("Parse Error");
				throw new NumberFormatException();
				//TODO exit application
			}
		} else {
			posAct = posSecond - 1; // <- step back before last space
			sub = line.substring(posFirst + 1, posSecond);
		}
    	
    	return sub;
    }
    
    /** 
     * getting name for use it ie. store it
     */
    public String getName() {
        
        return this.name;    
    }
    
    /** 
     * getting name for use it ie. store it
     */
    public void inputName() {
        new DataInput(this);   
    }
    /** 
     * sets the name variable in Game -> a String
     */
    public void setName(String newName) {
    	name = new String(newName);
    }
    /** 
     * synchronize the threads
     */
    public void synch(){
        
    }
    /** 
     * game ending sequence
     */
    public void end(){
        score.save(this);
        END = true;
        
    }
}

